import { computed, ref, watch } from 'vue';
import { defineStore } from 'pinia';
import {
  RouteLocationMatched,
  RouteLocationNormalizedLoaded,
  useRoute,
  useRouter,
} from 'vue-router';
import { TAB_VIEW_STORE } from '../constant';

export const routeExcludes = ['dashboard', 'login'] as const;
export const hideTabsRoutes = ['/dashboard'];
export const useTabViewsStore = defineStore(
  TAB_VIEW_STORE,
  () => {
    const router = useRouter();
    const currentRoute = useRoute();
    const tabsList = ref<RouteLocationNormalizedLoaded[]>([]);

    /** 给定的路由是否在排除名单里面 */
    const isInRouteExcludes = (route: RouteLocationNormalizedLoaded) => {
      return (
        route.meta?.hideInTabs || routeExcludes.some((n) => n === route.name)
      );
    };

    // 关闭所有
    const closeAllTab = () => {
      tabsList.value = [];
    };

    // 关闭其他
    const closeOther = (index: number) => {
      tabsList.value = tabsList.value.filter((_, idx) => idx === index);
    };

    const delTab = (route: RouteLocationNormalizedLoaded) => {
      const index = tabsList.value.findIndex(
        (item) => item.fullPath == route.fullPath,
      );

      // 是否删除当前页
      const isDelCurrentTab = currentRoute.path === tabsList.value[index].path;
      tabsList.value.splice(index, 1);
      if (isDelCurrentTab) {
        const currentRoute =
          tabsList.value[Math.max(0, tabsList.value.length - 1)];
        router.push(currentRoute);
      }
    };

    const getRawRoute = (
      route: RouteLocationNormalizedLoaded,
    ): RouteLocationNormalizedLoaded => {
      return {
        ...route,
        matched: route.matched.map((item) => {
          const { meta, path, name } = item;
          return { meta, path, name };
        }) as RouteLocationMatched[],
      };
    };

    /** 添加标签页 */
    const addTabs = (route: RouteLocationNormalizedLoaded) => {
      if (isInRouteExcludes(route)) {
        return false;
      }
      const isExists = tabsList.value.some((item) => item.path == route.path);
      if (!isExists) {
        tabsList.value.push(getRawRoute(route));
      }
      if (tabsList.value.length > Number(VITE_TABS_MAX_LENGTH)) {
        tabsList.value.splice(0, 1);
      }
      return true;
    };

    const hideTab = computed(() => {
      return hideTabsRoutes.includes(currentRoute.path);
    });

    watch(
      () => currentRoute.path,
      () => {
        addTabs(currentRoute);
      },
      { immediate: true },
    );

    const getterTabsList = computed(() => {
      return tabsList.value;
    });

    return {
      getterTabsList,
      hideTab,
      delTab,
      closeAllTab,
      closeOther,
    };
  },
  {
    persist: true,
  },
);
